#ifndef __GLESRenderTexture_H__
#define __GLESRenderTexture_H__


#include "U2GLESPreRequest.h"
#include "U2RenderTexture.h"
#include "U2GLESTexture.h"


U2EG_NAMESPACE_BEGIN


class GLESHardwarePixelBuffer;


/** GL surface descriptor. Points to a 2D surface that can be rendered to.
*/
struct _U2GLESShare U2GLESSurfaceDesc
{
public:
    GLESHardwarePixelBuffer *buffer;
    size_t zoffset;
    u2uint numSamples;

    U2GLESSurfaceDesc() : buffer(0), zoffset(0), numSamples(0) {}
};

/** Base class for GL Render Textures
*/
class _U2GLESShare U2GLESRenderTexture : public U2RenderTexture
{
public:
    U2GLESRenderTexture(const U2String &name, const U2GLESSurfaceDesc &target, bool writeGamma, u2uint fsaa);
    virtual ~U2GLESRenderTexture();
    bool requiresTextureFlipping() const { return true; }
};

/** Manager/factory for RenderTextures.
*/
class _U2GLESShare U2GLESRTTManager : public U2Singleton<U2GLESRTTManager>
{
public:
    virtual ~U2GLESRTTManager();

    /** Create a texture rendertarget object
    */
    virtual U2RenderTexture *createRenderTexture(const U2String &name, const U2GLESSurfaceDesc &target, bool writeGamma, u2uint fsaa) = 0;

     /** Check if a certain format is usable as rendertexture format
    */
    virtual bool checkFormat(PixelFormat format) = 0;

    /** Bind a certain render target.
    */
    virtual void bind(U2RenderTarget *target) = 0;

    /** Unbind a certain render target. This is called before binding another U2RenderTarget, and
        before the context is switched. It can be used to do a copy, or just be a noop if direct
        binding is used.
    */
    virtual void unbind(U2RenderTarget *target) = 0;

    virtual void getBestDepthStencil(GLenum internalFormat, GLenum *depthFormat, GLenum *stencilFormat)
    {
        *depthFormat = GL_NONE;
        *stencilFormat = GL_NONE;
    }

    /** Create a multi render target
    */
    virtual U2MultiRenderTarget* createMultiRenderTarget(const U2String & name);

    /** Get the closest supported alternative format. If format is supported, returns format.
    */
    virtual PixelFormat getSupportedAlternative(PixelFormat format);
};

/** U2RenderTexture for simple copying from frame buffer
*/
class U2GLESCopyingRTTManager;

class _U2GLESShare U2GLESCopyingRenderTexture : public U2GLESRenderTexture
{
public:
    U2GLESCopyingRenderTexture(U2GLESCopyingRTTManager *manager,
                           const U2String &name,
                           const U2GLESSurfaceDesc &target,
                           bool writeGamma, u2uint fsaa);

    virtual void getCustomAttribute(const U2String& name, void* pData);
};

/** Simple, copying manager/factory for RenderTextures. This is only used as the last fallback if
    both PBuffers and FBOs aren't supported.
*/
class _U2GLESShare U2GLESCopyingRTTManager : public U2GLESRTTManager
{
public:
    U2GLESCopyingRTTManager();
    virtual ~U2GLESCopyingRTTManager();

    /** @copydoc GLESRTTManager::createRenderTexture
    */
    virtual U2RenderTexture *createRenderTexture(const U2String &name, const U2GLESSurfaceDesc &target, bool writeGamma, u2uint fsaa);
    
    /** @copydoc GLESRTTManager::checkFormat
    */
    virtual bool checkFormat(PixelFormat format);

    /** @copydoc GLESRTTManager::bind
    */
    virtual void bind(U2RenderTarget *target);

    /** @copydoc GLESRTTManager::unbind
    */
    virtual void unbind(U2RenderTarget *target);
};


U2EG_NAMESPACE_END


#endif
